// 定义地图相关类型
export interface AMapPoint {
  lng: number;
  lat: number;
}

interface AMapOptions {
  key: string;
  element: HTMLElement | string;
  center: AMapPoint;
  zoom?: number;
  [key: string]: any; // 允许其他参数
}

interface MarkerOptions {
  position: AMapPoint;
  content?: string | HTMLElement;
  [key: string]: any; // 允许其他标记参数
}

// 声明高德地图全局变量类型
declare global {
  interface Window {
    AMap: any;
    AMapUI: any;
  }
}

/**
 * 高德地图API封装类，采用单例模式
 * 支持初始化、打点、点击事件和点位聚合功能
 */
class AMapWrapper {
  private static instance: AMapWrapper | null = null;
  private map: any = null;
  private markers: any[] = [];
  private cluster: any = null;
  private markerClickHandlers: ((position: AMapPoint, data?: any) => void)[] =
    [];
  private infoWindow: any = null; // 信息窗体实例，确保唯一性
  private mapClickListener: any = null; // 保存地图点击事件监听器
  // 在 AMapWrapper 类中添加新的私有属性
  private mapZoomListener: any = null; // 保存地图缩放事件监听器
  private mapLoadCallbacks: (() => void)[] = []; // 存储地图加载完成回调函数

  // 私有构造函数，防止外部实例化
  private constructor() {}

  /**
   * 获取单例实例
   * @returns AMapWrapper实例
   */
  public static getInstance(): AMapWrapper {
    if (!AMapWrapper.instance) {
      AMapWrapper.instance = new AMapWrapper();
    }
    return AMapWrapper.instance;
  }

  /**
   * 初始化地图
   * @param options 初始化参数
   * @returns 地图实例
   */
  public init(options: AMapOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      // 如果地图已存在，先销毁再重新初始化
      // if (this.map) {
      //   this.destroy();
      // }

      // 处理容器元素
      const container =
        typeof options.element === "string"
          ? document.getElementById(options.element)
          : options.element;

      if (!container) {
        reject(new Error("地图容器元素不存在"));
        return;
      }

      // 检查高德地图是否已加载
      if (!window.AMap) {
        // 动态加载高德地图API
        const script = document.createElement("script");
        script.src = `https://webapi.amap.com/maps?v=1.4.15&key=${options.key}`;
        script.onload = () =>
          this.initializeMap(options, container, resolve, reject);
        script.onerror = () => reject(new Error("高德地图API加载失败"));
        document.head.appendChild(script);
      } else {
        // // 已加载则直接初始化，并触发回调
        // this.executeMapLoadCallbacks();
        // 已加载则直接初始化
        this.initializeMap(options, container, resolve, reject);
      }
      //  this.initializeMap(options, container, resolve, reject);
    });
  }

  /**
   * 实际执行地图初始化的方法
   */
  private initializeMap(
    options: AMapOptions,
    container: HTMLElement,
    resolve: (value: any) => void,
    reject: (reason?: any) => void
  ): void {
    try {
      // 创建地图实例
      const mapConfig = {
        center: [options.center.lng, options.center.lat],
        zoom: options.zoom || 10,
        viewMode: "2D",
        mapStyle: "",
      };
      if (options.mapStyle) {
        mapConfig.mapStyle = options.mapStyle;
      }
      this.map = new window.AMap.Map(container, mapConfig);

      // 添加地图缩放事件监听器
      this.addMapZoomListener();

      // 地图API加载完成后触发回调
      this.executeMapLoadCallbacks();
      // 加载MarkerClusterer插件用于聚合
      this.loadClusterPlugin()
        .then(() => {
          resolve(this.map);
        })
        .catch(reject);
    } catch (error) {
      reject(error);
    }
  }

  /**
   * 获取当前地图实例
   * @returns 地图实例
   */
  public getMapInstance(): any {
    return this.map;
  }

  /**
   * 设置地图中心
   * @param position 中心坐标
   */
  public setCenter(position: AMapPoint): void {
    if (this.map) {
      this.map.setCenter([position.lng, position.lat]);
    }
  }

  /**
   * 设置地图缩放级别
   * @param zoom 缩放级别
   */
  public setZoom(zoom: number): void {
    if (this.map) {
      this.map.setZoom(zoom);
    }
  }
  /**
   * 添加POI点位到地图上
   * @param points 点位坐标数组
   * @param content 点位显示内容（可选）
   * @param data 点位关联数据（可选）
   */
  public addPOIs(
    points: AMapPoint[],
    content?: string | HTMLElement,
    data?: any[],
    // 添加一个可选的点击回调函数
    clickCallback?: (position: AMapPoint, data: any, marker: any) => void
  ): void {
    if (!this.map) {
      console.warn("地图未初始化");
      return;
    }

    // 创建标记数组
    const newMarkers: any[] = [];

    points.forEach((point, index) => {
      const marker = new window.AMap.Marker({
        position: [point.lng, point.lat],
        content: content,
        offset: new window.AMap.Pixel(-20, -20), // 根据实际图标调整偏移
      });

      // 绑定点击事件
      marker.on("click", () => {
        // 执行原有的点击处理函数
        this.markerClickHandlers.forEach((handler) => {
          handler(point, data ? data[index] : undefined);
        });

        // 执行传入的回调函数（用于显示信息窗体）
        if (clickCallback) {
          clickCallback(point, data ? data[index] : undefined, marker);
        }
      });

      newMarkers.push(marker);
    });

    // 添加到地图
    this.map.add(newMarkers);

    // 添加到聚合器
    if (this.cluster) {
      this.cluster.addMarkers(newMarkers);
    }

    // 保存标记引用
    this.markers.push(...newMarkers);
  }

  /**
   * 注册标记点击事件处理函数
   * @param handler 点击事件处理函数
   */
  public onMarkerClick(
    handler: (position: AMapPoint, data?: any) => void
  ): void {
    this.markerClickHandlers.push(handler);
  }

  /**
   * 清除所有POI点位
   */
  public clearPOIs(): void {
    if (this.map && this.markers.length > 0) {
      this.map.remove(this.markers);
      this.markers = [];

      // 重新设置聚合器
      if (this.cluster) {
        this.cluster.clearMarkers();
      }
    }
  }

  /**
   * 加载点位聚合插件
   */
  private loadClusterPlugin(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.cluster) {
        resolve();
        return;
      }

      window.AMap.plugin(["AMap.MarkerClusterer"], () => {
        try {
          this.cluster = new window.AMap.MarkerClusterer(this.map, [], {
            gridSize: 80,
            renderClusterMarker: (context: any) => {
              const div = document.createElement("div");
              const size = Math.round(Math.sqrt(context.count)) * 10;
              div.style.width = size + "px";
              div.style.height = size + "px";
              div.style.borderRadius = "50%";
              div.style.backgroundColor = "rgba(0, 150, 255, 0.7)";
              div.style.display = "flex";
              div.style.alignItems = "center";
              div.style.justifyContent = "center";
              div.style.color = "white";
              div.style.fontWeight = "bold";
              div.innerHTML = context.count;
              context.marker.setContent(div);
            },
          });
          resolve();
        } catch (error) {
          reject(error);
        }
      });
    });
  }

  /**
   * 创建或更新信息窗体
   * @param position 坐标位置
   * @param content 内容（可以是字符串或DOM元素）
   */
  public openInfoWindow(
    position: AMapPoint,
    content: string | HTMLElement
  ): void {
    // 如果信息窗体不存在，则创建
    if (!this.infoWindow) {
      this.infoWindow = new window.AMap.InfoWindow({
        isCustom: typeof content !== "string", // 如果是DOM元素，则使用自定义窗体
        content: content,
        offset: new window.AMap.Pixel(0, -30),
      });
    } else {
      // 如果已经存在，则更新内容
      this.infoWindow.setContent(content);
    }

    // 打开信息窗体
    this.infoWindow.open(this.map, [position.lng, position.lat]);

    // 添加地图点击事件监听器，用于点击外部关闭弹窗
    this.addMapClickListener();
  }
  /**
   * 添加地图缩放事件监听器
   */
  private addMapZoomListener(): void {
    if (!this.map) return;

    // 监听缩放开始事件
    this.mapZoomListener = () => {
      this.closeInfoWindow();
    };

    this.map.on("zoomstart", this.mapZoomListener);
  }

  /**
   * 移除地图缩放事件监听器
   */
  private removeMapZoomListener(): void {
    if (this.mapZoomListener && this.map) {
      this.map.off("zoomstart", this.mapZoomListener);
      this.mapZoomListener = null;
    }
  }

  /**
   * 关闭信息窗体
   */
  public closeInfoWindow(): void {
    if (this.infoWindow && this.map) {
      this.infoWindow.close();
    }
    // 移除地图点击事件监听器
    this.removeMapClickListener();
  }
  /**
   * 添加地图点击事件监听器
   */
  private addMapClickListener(): void {
    // 如果已经添加过监听器，则不再添加
    if (this.mapClickListener) {
      return;
    }

    // 添加地图点击事件监听器
    this.mapClickListener = (event: any) => {
      // 点击地图任意位置时关闭信息窗体
      this.closeInfoWindow();
    };

    this.map.on("click", this.mapClickListener);
  }

  /**
   * 移除地图点击事件监听器
   */
  private removeMapClickListener(): void {
    if (this.mapClickListener && this.map) {
      this.map.off("click", this.mapClickListener);
      this.mapClickListener = null;
    }
  }
  /**
   * 清理所有监听器和资源
   */
  public destroy(): void {
    this.removeMapClickListener();
    this.removeMapZoomListener();
    this.clearPOIs();
    this.infoWindow = null;
    this.map = null;
    AMapWrapper.instance = null;
  }
  /**
   * 注册地图加载完成回调函数
   * @param callback 地图加载完成后的回调函数
   */
  public onMapLoad(callback: () => void): void {
    this.mapLoadCallbacks.push(callback);
  }

  /**
   * 执行所有地图加载完成回调函数
   */
  private executeMapLoadCallbacks(): void {
    this.mapLoadCallbacks.forEach((callback) => {
      try {
        callback();
      } catch (error) {
        console.error("地图加载回调执行出错:", error);
      }
    });
    // 清空回调函数列表，避免重复执行
    this.mapLoadCallbacks = [];
  }
}

export default AMapWrapper;
